import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { toEntity } from "src/utils/dto2Entity";
import { Repository } from "typeorm";
import { MenuDto } from "./dto/menu.dto";
import { SearchMenuDto } from "./dto/search-menu.dto";
import { MenuEntity } from "./entities/menu.entity";
import { PageResponseResult } from "@/common/tools/page.response.result";
import { Deleted } from "@/common/enums/deleted.enum";
import { TenantService } from "@/modules/tenant/tenant.service";

@Injectable()
export class MenuService {
  constructor(private readonly tenantService: TenantService) {}
  @InjectRepository(MenuEntity)
  private readonly menuRepository: Repository<MenuEntity>;

  /**
   * 获取菜单分页列表
   * @param searchMenuDto 搜索dto
   */
  async getMenuPageList(tenantId: number, searchMenuDto: SearchMenuDto) {
    const { page, keyword } = searchMenuDto;
    const { current, size } = page;
    const skip = (current - 1) * size;
    const tenantRepository = await this.getTenantRepository(tenantId);
    const queryBuilder = tenantRepository.createQueryBuilder();
    if (keyword) {
      queryBuilder.where(`menu_name=:menuName`, { menuName: keyword });
    }
    const entities = await queryBuilder
      .orderBy("create_time", "DESC")
      .offset(skip)
      .limit(size)
      .getMany();
    page.total = await queryBuilder.getCount();
    const result = new PageResponseResult<MenuEntity[]>(page.total, entities);
    return result;
  }

  /**
   * 获取菜单列表
   */
  async getMenuList(tenantId: number) {
    const tenantRepository = await this.getTenantRepository(tenantId);
    const entities = await tenantRepository.find();
    return entities;
  }

  /**
   * 根据菜单id获取菜单信息
   * @param id 编号
   */
  async getMenuById(tenantId: number, id: number) {
    const tenantRepository = await this.getTenantRepository(tenantId);
    const entity = await tenantRepository.findOne({
      where: {
        id,
      },
    });
    return entity;
  }

  /**
   * 根据菜单名称获取菜单信息
   * @param menuName 菜单名称
   */
  async getMenuByMenuName(tenantId: number, menuName: string) {
    const tenantRepository = await this.getTenantRepository(tenantId);
    const entity = await tenantRepository.findOneBy({
      menuName,
    });
    return entity;
  }

  /**
   * 创建菜单
   * @param userDto 菜单dto
   */
  async createMenu(tenantId: number, menuDto: MenuDto) {
    const tenantRepository = await this.getTenantRepository(tenantId);
    const menu = await tenantRepository.findOneBy({
      menuCode: menuDto.menuCode,
      menuName: menuDto.menuName,
      pId: menuDto.pId,
    });
    if (menu) {
      throw new HttpException("操作失败,菜单名已使用.", HttpStatus.BAD_REQUEST);
    }
    const menuEntity = new MenuEntity();
    toEntity(menuDto, menuEntity);
    menuEntity.deleted = Deleted.NoDeleted;
    menuEntity.createTime = new Date();
    await tenantRepository.insert(menuEntity);
  }

  /**
   * 修改菜单
   * @param id 编号
   * @param userDto 菜单dto
   */
  async updateMenuById(tenantId: number, id: number, menuDto: MenuDto) {
    const menu = await this.getMenuById(tenantId, id);
    if (!menu) {
      throw new HttpException(
        "操作失败,未找到菜单信息.",
        HttpStatus.BAD_REQUEST
      );
    }
    const menuEntity = new MenuEntity();
    toEntity(menuDto, menuEntity);
    const tenantRepository = await this.getTenantRepository(tenantId);
    await tenantRepository.update(id, menuEntity);
  }

  /**
   * 删除菜单
   * @param id 编号
   */
  async removeMenuById(tenantId: number, id: number) {
    const tenantRepository = await this.getTenantRepository(tenantId);
    await tenantRepository.delete(id);
  }
  private async getTenantRepository(
    tenantId: number
  ): Promise<Repository<MenuEntity>> {
    const tenantConnection = await this.tenantService.getTenantConnection(
      tenantId
    );
    return tenantConnection.getRepository(MenuEntity);
  }
}
